package com.gonsin.project.creator.utils;

import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.runtime.ScriptObject;

import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.gonsin.project.creator.create.IJavaScriptBinder.JS_PREFIX;

public class JsUtils {

    public static void runJs(String js, Object bind) throws ScriptException {
        ScriptEngineManager manager = new ScriptEngineManager();
//        manager.getEngineFactories().forEach(f -> System.out.println(f.getEngineName()));
        ScriptEngine engine = manager.getEngineByName("js");
//        ScriptEngine engine = manager.getEngineByName("nashorn");
//        ScriptEngine engine = manager.getEngineByName("ecmascript");
        Bindings bindings = engine.createBindings();
        bindings.put("java", bind);
        engine.eval(JS_PREFIX + js, bindings);
    }


    /**
     * javascript对象转java
     */
    public static Object toObject(ScriptObjectMirror mirror) {
        if (mirror.isEmpty()) {
            return null;
        }
        if (mirror.isArray()) {
            List<Object> list = new ArrayList<>();
            for (Map.Entry<String, Object> entry : mirror.entrySet()) {
                Object result = entry.getValue();
                if (result instanceof ScriptObjectMirror) {
                    list.add(toObject((ScriptObjectMirror) result));
                } else {
                    list.add(result);
                }
            }
            return list;
        }

        Map<String, Object> map = new HashMap<>();
        for (Map.Entry<String, Object> entry : mirror.entrySet()) {
            Object result = entry.getValue();
            if (result instanceof ScriptObjectMirror) {
                map.put(entry.getKey(), toObject((ScriptObjectMirror) result));
            } else {
                if(result instanceof Map){
                    map.put(entry.getKey(), handleMap((Map<String, Object>) result));
                } else {
                    map.put(entry.getKey(), result);
                }
            }
        }

        return map;
    }


    private static Map<String, Object> handleMap(Map<String, Object> mirror){
        Map<String, Object> map = new HashMap<>();
        for (Map.Entry<String, Object> entry : mirror.entrySet()) {
            Object result = entry.getValue();
            if (result instanceof ScriptObjectMirror) {
                map.put(entry.getKey(), toObject((ScriptObjectMirror) result));
            } else {
                if(result instanceof Map){
                    map.put(entry.getKey(), handleMap((Map<String, Object>) result));
                } else {
                    map.put(entry.getKey(), result);
                }
            }
        }
        return map;
    }
}
